const request = require('request');

module.exports = function (options) {
  const { tokenUrl, userUrl, callbackUrl, clientId, clientSecret } = options;
  const { emailPostfix, emailKey, userKey } = options;

  this.bindHook('third_login', (ctx) => {
    let code = ctx.request.body.code || ctx.request.query.code;

    return new Promise((resolve, reject) => {
      request.post({
        url: tokenUrl,
        form: {
          client_id: clientId,
          client_secret: clientSecret,
          grant_type: 'authorization_code',
          code: code,
          redirect_uri: callbackUrl
        }
      }, function (error, response, tokenBody) {
        if (!error && response.statusCode == 200) {
          let res = JSON.parse(tokenBody);
          resolve(res.access_token);
        } else {
          reject(new Error(tokenBody))
        }
      })
    }).then(accessToken => {
      return new Promise((resolve, reject) => {
        request.get({
          url: userUrl,
          headers: {
            Authorization: 'Bearer ' + accessToken
          }
        }, function (error, response, userBody) {
          if (!error && response.statusCode == 200) {
            let result = JSON.parse(userBody);
            if (result) {
              let username = userKey ? result[userKey] || result.username : result.username;
              let email = userKey ? result[emailKey] || result.email : result.email;

              if (!username) {
                reject(new Error('无法获取到用户名称'));
              }

              if (!email) {
                if (username && emailPostfix) {
                  email = username + emailPostfix;
                } else {
                  reject(new Error('无法获取用户email'));
                }
              }

              let ret = {
                email: email,
                username: username
              };
              resolve(ret);
            } else {
              reject(new Error(userBody));
            }
          }
          reject(new Error(userBody));
        });
      })
    }).catch(err => {
      return new Promise((resolve, reject) => {
        reject(err)
      })
    })
  })
}
